﻿using DLog.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DLog.Common;
using System.IO;

namespace DLog.Access
{
    public class NotepadDal : IDal
    {
        private string path;
        readonly static string splitstr = "[#]";

        private FileInfo[] GetSamePathFiles()
        {
            return GetSamePathFiles(null, null, null);
        }

        private FileInfo[] GetSamePathFiles(int levelLog)
        {
            return GetSamePathFiles(levelLog, null, null);
        }

        private FileInfo[] GetSamePathFiles(DateTime CreateStartDate, DateTime CreateEndDate)
        {
            return GetSamePathFiles(null, CreateStartDate, CreateEndDate);
        }

        private FileInfo[] GetSamePathFiles(int? levelLog, DateTime? CreateStartDate, DateTime? CreateEndDate)
        {
            FileInfo fi = new FileInfo(path);
            DirectoryInfo di = fi.Directory;
            FileInfo[] fis = di.GetFiles("*.txt", SearchOption.TopDirectoryOnly);
            List<FileInfo> fiList = new List<FileInfo>();
            if (levelLog != null && CreateStartDate != null && CreateEndDate != null)
            {
                foreach (FileInfo fInfo in fis)
                {
                    if ((fInfo.Name.Contains("[LogLevel]" + levelLog.ToString() + "[LogLevel]") || !fInfo.Name.Contains("[LogLevel]")) && !(fInfo.CreationTime > CreateEndDate && fInfo.LastWriteTime < CreateStartDate))
                    {
                        fiList.Add(fInfo);
                    }
                }
            }
            else if (levelLog != null)//search contain levellog log file
            {
                foreach (FileInfo fInfo in fis)
                {
                    if (fInfo.Name.Contains("[LogLevel]" + levelLog.ToString() + "[LogLevel]") || !fInfo.Name.Contains("[LogLevel]"))
                    {
                        fiList.Add(fInfo);
                    }
                }
            }
            else if (CreateStartDate != null && CreateEndDate != null)//search contain createDate log file
            {
                foreach (FileInfo fInfo in fis)
                {
                    if (!(fInfo.CreationTime > CreateEndDate && fInfo.LastWriteTime < CreateStartDate))
                    {
                        fiList.Add(fInfo);
                    }
                }
            }
            else
            {
                return fis;
            }
            return fiList.ToArray();
        }

        public NotepadDal(string connectionString)
        {
            path = RuleConnectionstring(connectionString);
        }

        /// <summary>
        /// Based on the rule change string
        /// </summary>
        /// <param name="pathStr"></param>
        /// <returns></returns>
        public string RuleConnectionstring(string pathStr)
        {
            if (pathStr.Contains("@Hour"))
            {
                pathStr = pathStr.Replace("@Hour", DateTime.Now.ToString("yyyy-MM-dd hh"));
            }
            else if (pathStr.Contains("@Date"))
            {
                pathStr = pathStr.Replace("@Date", DateTime.Now.ToString("yyyy-MM-dd"));
            }
            else if (pathStr.Contains("@Month"))
            {
                pathStr = pathStr.Replace("@Month", DateTime.Now.ToString("yyyy-MM"));
            }
            return pathStr;
        }

        public string RuleConnectionstring(string pathStr, int logLevel)
        {

            if (pathStr.Contains("@LogLevel"))
            {
                pathStr = pathStr.Replace("@LogLevel", logLevel.ToString());
            }
            return pathStr;
        }
        /// <summary>
        /// translate line string to log model
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        private static LogModel LineStringToLogModel(string line)
        {
            string[] splits = new string[] { splitstr };
            string[] strs = line.Split(splits, StringSplitOptions.None);
            LogModel logmodel = new LogModel()
            {
                LogId = strs[1],
                CreateDate = Convert.ToDateTime(strs[3]),
                Origin = strs[5],
                LogLevel = Convert.ToInt32(strs[7]),
                Message = strs[9],
                StackTrade = strs[11],
            };
            return logmodel;
        }

        public LogModel SelectModel(string logId)
        {
            FileInfo[] files = this.GetSamePathFiles();
            List<string> lines = new List<string>();
            LogModel logmodel = null;
            foreach (FileInfo file in files)
            {
                lines = NotepadHelper.LogRead("LogId" + splitstr + logId, file.FullName);
                if (lines.Count > 0)
                    break;
            }
            if (lines.Count > 0)
            {
                logmodel = LineStringToLogModel(lines[0]);
            }
            return logmodel;
        }

        public List<LogModel> SelectList()
        {
            FileInfo[] files = this.GetSamePathFiles();
            List<LogModel> logModelList = new List<LogModel>();
            List<string> lines = new List<string>();
            foreach (FileInfo file in files)
            {
                lines.AddRange(NotepadHelper.LogRead(file.FullName));
            }
            foreach (string line in lines)
            {
                logModelList.Add(LineStringToLogModel(line));
            }
            return logModelList;
        }

        public List<LogModel> SelectList(int logLevel)
        {
            FileInfo[] files = this.GetSamePathFiles(logLevel);
            List<LogModel> logModelList = new List<LogModel>();
            List<string> lines = new List<string>();
            string condition = "LogLevel" + splitstr + logLevel.ToString();
            foreach (FileInfo file in files)
            {
                lines.AddRange(NotepadHelper.LogRead(condition, file.FullName));
            }
            foreach (string line in lines)
            {
                logModelList.Add(LineStringToLogModel(line));
            }
            return logModelList;
        }

        public List<LogModel> SelectList(int pageIndex, int pageSize, out int totalCount)
        {
            FileInfo[] files = this.GetSamePathFiles();
            List<LogModel> logModelList = new List<LogModel>();
            List<string> lines = new List<string>();
            totalCount = 0;
            lines.AddRange(NotepadHelper.LogRead(null, null, null, null, null, pageIndex, pageSize, files.Select(p => p.FullName).ToList<string>(), out totalCount));
            foreach (string line in lines)
            {
                logModelList.Add(LineStringToLogModel(line));
            }
            return logModelList;
        }

        public List<LogModel> SelectList(int logLevel, int pageIndex, int pageSize, out int totalCount)
        {
            FileInfo[] files = this.GetSamePathFiles(logLevel);
            List<LogModel> logModelList = new List<LogModel>();
            List<string> lines = new List<string>();
            string condition = "LogLevel" + splitstr + logLevel.ToString();
            totalCount = 0;
            lines.AddRange(NotepadHelper.LogRead(condition, null, null, null, null, pageIndex, pageSize, files.Select(p => p.FullName).ToList<string>(), out totalCount));
            foreach (string line in lines)
            {
                logModelList.Add(LineStringToLogModel(line));
            }
            return logModelList;
        }

        public List<LogModel> SelectList(DateTime createStartDate, DateTime createEndDate, int pageIndex, int pageSize, out int totalCount)
        {
            FileInfo[] files = this.GetSamePathFiles(createStartDate, createEndDate);
            List<LogModel> logModelList = new List<LogModel>();
            List<string> lines = new List<string>();
            string fieldName = "CreateDate";
            totalCount = 0;
            lines.AddRange(NotepadHelper.LogRead(null, fieldName, splitstr, createStartDate, createEndDate, pageIndex, pageSize, files.Select(p => p.FullName).ToList<string>(), out totalCount));
            foreach (string line in lines)
            {
                logModelList.Add(LineStringToLogModel(line));
            }
            return logModelList;
        }

        public List<LogModel> SelectList(int logLevel, DateTime createStartDate, DateTime createEndDate, int pageIndex, int pageSize, out int totalCount)
        {
            FileInfo[] files = this.GetSamePathFiles(logLevel, createStartDate, createEndDate);
            List<LogModel> logModelList = new List<LogModel>();
            List<string> lines = new List<string>();
            string fieldName = "CreateDate";
            string condition = "LogLevel" + splitstr + logLevel.ToString();
            totalCount = 0;
            lines.AddRange(NotepadHelper.LogRead(condition, fieldName, splitstr, createStartDate, createEndDate, pageIndex, pageSize, files.Select(p => p.FullName).ToList<string>(), out totalCount));
            foreach (string line in lines)
            {
                logModelList.Add(LineStringToLogModel(line));
            }
            return logModelList;
        }

        public int Insert(LogModel lm)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("LogId" + splitstr + lm.LogId + splitstr);
            sb.Append("CreateDate" + splitstr + lm.CreateDate.ToString() + splitstr);
            sb.Append("Origin" + splitstr + (string.IsNullOrWhiteSpace(lm.Origin) ? "none" : lm.Origin) + splitstr);
            sb.Append("LogLevel" + splitstr + lm.LogLevel.ToString() + splitstr);
            sb.Append("Message" + splitstr + lm.Message + splitstr);
            sb.Append("StackTrade" + splitstr + (string.IsNullOrWhiteSpace(lm.StackTrade) ? "none" : lm.StackTrade));
            NotepadHelper.LogWrite(sb.ToString(), RuleConnectionstring(path, lm.LogLevel));
            return 1;
        }

        public int Delete(string logId)
        {
            FileInfo[] files = this.GetSamePathFiles();
            foreach (FileInfo file in files)
            {
                if (NotepadHelper.DeleteLogInFile("LogId" + splitstr + logId, file.FullName))
                {
                    return 1;
                }
            }
            return 0;
        }

        public int Delete(LogModel lm)
        {
            FileInfo[] files = this.GetSamePathFiles(lm.LogLevel, lm.CreateDate, lm.CreateDate);
            foreach (FileInfo file in files)
            {
                if (NotepadHelper.DeleteLogInFile("LogId" + splitstr + lm.LogId, file.FullName))
                {
                    return 1;
                }
            }
            return 0;
        }
    }
}
